/**
 * 得到一个路径字典对象
 * @param skus   商品的所有sku属性集合
 */
import bwPowerSet from '@/vender/power-set'
import { splitter } from '@/constant'

function getPathMap(skus) {
  // 1.得到所有的sku集合, props.goods.skus
  // 2.从所有的sku中筛选出有效的sku
  // 3.根据有效的sku使用power-set算法得到子集
  // 4.根据子集往字典对象中存储 key-value

  const pathMap = {}
  skus.forEach(sku => {
    // 1.过滤出有库存有效的sku
    if (sku.inventory > 0) {
      // 计算当前库存的sku的子集
      // 例如: [1, 2, 3] ==> [[1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]]
      // 可选值数组
      const valueArr = sku.specs.map(item => item.valueName)
      // 得到sku可选值数组子集
      const valueArrPowerSet = bwPowerSet(valueArr)

      // valueArrPowerSet: [[], ['米色'], ['120cm'], ['米色', '120cm']]
      // console.log(valueArrPowerSet)
      // 遍历子集, 往pathMap插入数据, 设置给路径字典对象
      valueArrPowerSet.forEach(arr => {
        // 根据arr得到字符串的key, 约定key是: ['蓝色', '美国'] ==> '蓝色★美国'
        const key = arr.join(splitter)

        // 给pathMap设置数据
        if (pathMap[key]) {
          // 已经有key往数组追加
          pathMap[key].push(sku.id)
        } else {
          // 没有key设置一个数组
          pathMap[key] = [sku.id]
        }
      })
    }
  })

  return pathMap
}

/**
 * 更新按钮禁用状态
 * @param specs   商品的分类信息
 * @param pathMap 路径对象
 */
function updateDisableStatus(specs, pathMap) {
  // 1.约定每一个按钮由本身的disabled数据来控制

  // 第一层遍历: 属性所有分类:  [{name: '颜色', values: [xxx]}, {name: '尺寸', values: [xxx]}]
  // i索引, 对应了第几排分类  i = 0 --> 颜色, i = 1 --> 尺寸
  specs.forEach((item, i) => {

    // 把选中的规格集合放在第一层遍历的内部的原因
    // 是因为在第二层循环的时候, 对规格数组修改, 下次遍历第一层需要重新初始化这个规格数组
    const selectedValues = getSelectedValues(specs)

    // 第二层遍历: 指定属性的细粒度分类sku, 如颜色属性下: values: [{name: '米色', picture}....]
    item.values.forEach(val => {
      // 2.判断当前是否选中, 是选中不用判断
      if (val.selected) return
      // 3.拿当前的值按照顺序填入选中的值数组
      selectedValues[i] = val.name
      // 4.剔除undefined数据, 按照分隔符拼接key  value => value !== undefined --> 简化 value => value
      const key = selectedValues.filter(value => value !== undefined).join(splitter)
      // 5.去路径字典中查找是否有数据, 有可以点击, 没有就禁用(true)
      // console.log(pathMap['米色★100cm'])  ==>  undefined
      val.disabled = !pathMap[key]
    })
  })
}

/**
 * 得到当前选中规格集合 (是有顺序的)
 * @param specs
 * @return {*[]}
 */
const getSelectedValues = (specs) => {
  const arr = []
  // 举例: 属性顺序  颜色 -> 尺寸 -> 产地
  // 点击 尺寸: 10cm      ==> 得到数组  [undefined, '10cm', undefined]
  // 再次点击 颜色: 青色   ==> 得到数组  ['蓝色', '10cm', undefined]
  // 再次点击 颜色: 青色   ==> 得到数组  [undefined, '10cm', undefined]
  // 组件初始化           ==> 得到数组  [undefined, undefined, undefined]
  specs.forEach(item => {
    // 选中的按钮对象
    const selectedVal = item.values.find(val => val.selected)
    // 当find算子没有找到, selectVal为undefined
    arr.push(selectedVal ? selectedVal.name : undefined)
  })

  return arr
}

/**
 * 根据传入的skuId选中对应规格按钮
 * @param goods
 * @param skuId
 */
const initDefaultSelected = (goods, skuId) => {
  // 1.找出sku信息
  const { specs } = goods.skus.find(sku => sku.id === skuId)

  if (specs && specs.length > 0) {
    // 2.遍历sku数组          | specs 属性数组, 数组元素顺序 颜色 -> 尺码
    // sku -> 属性的笛卡尔积   | skus  商品sku数组, 数组中每个specs属性数组顺序 颜色 -> 尺码
    specs.forEach((spec, i) => {
      const sku = goods.specs[i]
        .values.find(val => val.name === spec.valueName)
      sku.selected = true
    })
  }
}

export {
  getPathMap,
  updateDisableStatus,
  getSelectedValues,
  initDefaultSelected
}
